package seismosurfer.util;

import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import seismosurfer.data.SourceData;
import seismosurfer.database.CountryDAO;
import seismosurfer.domain.Quake;
import seismosurfer.servlets.util.SessionHandler;

import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PropUtils;

/**
 * A <a href="http://www.martinfowler.com/eaaCatalog/registry.html">Registry</a>
 * implementation for the server.
 *
 */
public class Registry {

    public static final String COUNTRIES = "countries";

    public static final String PROPERTIES = "openmap.properties";

    public static final String EMAIL_PROPERTIES = "email.properties";

    public static final String JDBC = "jdbc";

    public static final String SOURCE_NAMES = "sourceNames";

    public static final String DATA_SOURCE = "dataSource";

    public static final String CACHE = "cache";

    private static Registry instance = new Registry();

    private Map registry = new HashMap();

    protected Registry() {
    }
    
    /**
     * Gets a list with all the countries
     * in db.
     * 
     * @return a List of CountryData
     */
    public static List getCountries() {
        List result = (List) instance.registry.get(COUNTRIES);
        if (result == null) {
            result = CountryDAO.getCountries();
            setCountries(result);
        }
        return result;
    }
    
    /**
     * Gets a set of the data source names.
     * 
     * @return a Set of the data source names
     */
    public static Set getSourceNames() {
        Set result = (Set) instance.registry.get(SOURCE_NAMES);

        if (result == null) {
            result = new HashSet();
            Quake q = new Quake();

            List sources = q.getSources();
            for (int i = 0; i < sources.size(); i++) {
                SourceData sd = (SourceData) sources.get(i);
                result.add(sd.getSource());
            }
            setSourceNames(result);
        }

        return result;
    }
    
    /**
     * Gets a Properties object with email related
     * properties. 
     * 
     * @return a Properties object
     */
    public static Properties getEmailProperties() {
        return getProperties(EMAIL_PROPERTIES, "/WEB-INF/email.properties");
    }
    
    /**
     * Gets a Properties object given the path of
     * the properties file and a corresponding key.
     * 
     * @param which an identifier for the properties file
     * @param path the path to the properties file
     * @return a Properties object
     */
    protected static Properties getProperties(String which, String path) {
        Properties p = (Properties) instance.registry.get(which);
        if (p == null) {
            p = new Properties();

            InputStream in = SessionHandler.getServletContext()
                    .getResourceAsStream(path);

            Debug.output("Reading properties file " + path + " from disk...");

            boolean loaded = PropUtils.loadProperties(p, in);
            if (!loaded) {
                throw new SeismoException(
                        "Properties file could not be loaded.");
            }
            instance.registry.put(which, p);
        }
        return p;

    }
    
    /**
     * Gets the name of the data source.
     * 
     * @return the name of the data source
     */
    public static String getDBDataSourceName() {
        return SessionHandler.getServletContext().getInitParameter(DATA_SOURCE);
    }
    
    /**
     * Gets the url needed for the JDBC connection.
     * 
     * @return the url needed for the JDBC connection
     */
    public static String getJDBCURL() {
        return (String) instance.registry.get(JDBC);
    }
    
    /**
     * Stores the url for the JDBC connection.
     * 
     * @param jdbcURL the url for the JDBC connection
     */
    public static void setJDBCURL(String jdbcURL) {
        instance.registry.put(JDBC, jdbcURL);
    }
    
    /**
     * Gets a Properties object with the application
     * properties.
     * 
     * @return a Properties object
     */
    public static Properties getOpenmapProperties() {
        return getProperties(PROPERTIES, "/properties/openmap.properties");
    }    
    
    protected static void setCountries(List countries) {
        instance.registry.put(COUNTRIES, countries);
    }

    protected static void setSourceNames(Set sourceNames) {
        instance.registry.put(SOURCE_NAMES, sourceNames);
    }

}